/**********************************************************************\

 Copyright 2012 Diggory Blake

 This file is part of klip-engine

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.

\**********************************************************************/
#pragma once

#include <bitset>

class kMouseInput;
class kKeyboardInput;

#include "kcommon.h"
#include "kbase.h"
#include "kmath.h"
#include "keinput.h"

class kMouseInput : public kBase {
public:
	virtual keButtonState getMouseButtons(keMouseButtons buttons) = 0;
	virtual kVec2i getMousePos() = 0;
	virtual kVec2i getMouseMove() = 0;
	virtual kVec2 getMouseMoveRaw() = 0;
	virtual int getMouseWheel() = 0;
	virtual bool getMouseOver() = 0;

	kDelegate<void (kBase*, keMouseButtons)>	onMouseDown;
	kDelegate<void (kBase*, keMouseButtons)>	onMouseUp;
	kDelegate<void (kBase*, const kVec2i&)>		onMouseMove;
	kDelegate<void (kBase*)>					onMouseEnter;
	kDelegate<void (kBase*)>					onMouseLeave;
	kDelegate<void (kBase*, int)>				onMouseWheel;
};

class kKeyboardInput : public kBase {
public:
	virtual keButtonState getKey(keKeyCode code) = 0;

	kDelegate<void (kBase*, keKeyCode)>			onKeyDown;
	kDelegate<void (kBase*, keKeyCode)>			onKeyUp;
	kDelegate<void (kBase*, keKeyCode)>			onKeyPress;
	kDelegate<void (kBase*, tchar)>				onKeyChar;
};

class kBasicMouseInput : public kMouseInput {
private:
	kBase* _sender;
	keMouseButtons _prevButtons;
	keMouseButtons _buttons;
	kVec2i _prevPos;
	kVec2i _pos;
	kVec2 _rawMove;
	int _scroll;
	bool _over;

public:
	inline kBasicMouseInput() {
		_sender = 0;
		_prevButtons = keMouseButton_None;
		_buttons = keMouseButton_None;
		_scroll = 0;
		_over = false;
	}

	inline void setSender(kBase* sender) {
		_sender = sender;
	}

	inline void preUpdate() {
		_prevButtons = _buttons;
		_prevPos = _pos;
		_rawMove.x = 0.0f;
		_rawMove.y = 0.0f;
		_scroll = 0;
	}
	void updateMousePos(const kVec2i& pos);
	inline void updateMouseRawMove(const kVec2& rawMove) {
		_rawMove = rawMove;
	}
	void updateMouseButtons(keMouseButtons buttons, bool down);
	void updateMouseWheel(int scroll);
	void updateMouseOver(bool over);

	virtual keButtonState getMouseButtons(keMouseButtons buttons);
	virtual kVec2i getMousePos();
	virtual kVec2i getMouseMove();
	virtual kVec2 getMouseMoveRaw();
	virtual int getMouseWheel();
	virtual bool getMouseOver();
};

class kBasicKeyboardInput : public kKeyboardInput {
private:
	kBase* _sender;
	std::bitset<256> _prevKeys;
	std::bitset<256> _keys;

public:
	inline kBasicKeyboardInput() {
		_sender = 0;
	}

	inline void setSender(kBase* sender) {
		_sender = sender;
	}

	void updateKey(keKeyCode code, bool down);
	inline void preUpdate() {
		_prevKeys = _keys;
	}

	virtual keButtonState getKey(keKeyCode code);
};
